Contrac Security - Auditing
Synchronization Link Tree
Intro.
合約審計(Smart Contract Auditing)實際上是由第三方對智能合約進行完整的檢查,包含找出系統設計的漏洞或不完整、邏輯與語法錯誤、潛在風險與警告等,有的審計公司甚至會提出 Gas 優化與使用者體驗優化。審計的時長可能有 2 天到數個月不等,不過通常在兩個禮拜前後可以完成(越簡單的合約當然就越快)。價格方面大型 Project 很容易落在一萬美金至四萬美金之間,小型 Project 則是五百美金到一萬五美金之間,不過這個部分不一定,得端看項目方預算、項目大小、審計公司品牌與提供的服務而訂。
審計完以後會提供一份報告給予項目方作為證書和分析,這份報告同樣的也是給予 User 閱讀,可以幫助用戶在短時間內迅速了解專案的內容與潛在風險。當然沒有人能夠「完美地」未來會發生的錯誤,因此報告中每個細項通常都會以「分數」型態表示,以區分高風險與低風險的段落。
審計某種程度上也是這間審記公司對這份「合約」的保證,如果今天這份合約出了什麼問題,無論是被外部入侵或者內部捲款潛逃,提供合約審計的公司都難辭其咎,因此這份工作非常吃品牌形象與過往經手的案例。
合約審計其實是一門大功課,非常吃開發經驗以及對語言的了解程度。現在很多審計工作室主要都是逐行的 Code Review 加上一串的 Check List 然後依序地把程式碼檢查完,同時了解程式碼的邏輯後撰寫測試等等,再輔以分析工具的使用。這邊主要介紹一些工作室的 Check List 以及流程步驟,幫助大家可以更快知道合約裡面哪些地方該注意。
Smart Contract Security Strategy
檢查的內容包含我們之前一個章節提到的所有 Vulnerability,例如 Random number、Reentrancy attack、Over and underflows、Replay attack、Short address attack、Front Running 等,這些東西通常都會包含在 Code Review 與撰寫的壓力測試之中,因為每個專案的程式碼系統設計概念都不同,要如何在程式碼之中發現這個問題非常的仰賴開發經驗。
除了我們常常探討的缺陷或攻擊問題之外,Auuditing 還需要找出潛在的風險,例如 Gas Limit 太低會不會造成運作上的意外,訂價模型中是否有滑價問題或流動性枯竭等風險,全域變數或區塊訊息的錯誤情況(timestamp、MEV、Difficulty)、系統之中是否含有單點錯誤等等。
項目方在撰寫合約時可能會繼承函式庫或者 Interface,通常大家都不會去細看自己引用的那些 API 或者 Library(從最基本的 ERC-20 Token 到 Oracle 引入),但是這裡面也許有許多潛在的風險或者對接上的不完全,審計公司也必須發現這個部分的潛在危機。
此外也會有模擬使用者交互運作系統的情況,這些部分都與寫測試非常類似,反正測試會寫到的內容審計都應該要包含在裡面。另外一個部分就是工具的利用,無論是測試還是分析都需要仰賴許多工具,這個部分在前文以及後文我都會不斷提到。
Blockchain Security Checklist
通常一個審計或檢查過程都會參考這份文件 Smart Contract Weakness Classification and Test Cases 中的內容,簡單來說我們上述提到的 Random number、Reentrancy attack、Over and underflows、Replay attack、Short address attack、Front Running 這些 Vulnerability 都會在裡面被提到。
Good Code
這個部分有點像是如何寫出一份「好的程式碼」,NatSpec Format 可以幫助開發團隊內部溝通以及審計公司檢查上快速地釐清函式內容,越詳細的文件敘述可以減少很多浪費掉的時間。
另外要提升程式碼的檢視,還有大量詳細(但不是濫用)的 events logging、assertion,能夠在測試時更迅速的了解運作情況。
Auditing Company / Studio
以下是最知名的審計公司:
在觀察完這些審計公司的合作夥伴之後會發現某些大項目會有跟兩間以上的審計公司合作,其實在業界一個成熟的項目都會這樣子選擇,只要預算夠能夠最大幅度的增加安全性當然是最好的,對他們來說跟日後的獲利相比這點錢可不能省阿!
Diligence
Consensys - Diligence 是一個提供智能合約安全與審計的服務,
主要提供以下五點的安全檢查步驟:
- 自動化安全分析(MythX):
- 插入程式碼標註測試(Scribble):
- 檢測 Runtime 執行,需要特別撰寫 Function 的 Spec,會在裡面加入 assertion 檢測
- 模糊測試(Fuzzing):
- 經過 Scribble 之後的 Fuzzing Testing
- 單點抽查(Spot Check):
- 第三方安全審計(Auditing):
Solidity Finance
Solidity Finance
- Automated Testing
- 使用自動化的分析工具以及手動撰寫的測試進行合約檢查
- In-Depth Manual Review
- 逐行進行 Code review,這是整個審計過程最重要的步驟
- Resolution of Issues
- 和團隊進行討論並給予建議,除了提供安全檢查之外也會提供 Gas 優化的建議
- Publishing the Audit Report
- 提供一份的完整且易讀的報告,包含潛在的風險以及整份合約的其他建議
- 這份報告的重點其實在於提供 User 一個途徑去了解這個合約在做什麼
Closing
Reference
Appendix: CryptoFin's Solidity Auditing Checklist
參考一下 CryptoFin's Solidity Auditing Checklist 的內容:
Core Checks
These are basic checks to undertake with any contract. Our checklist reflects Solidity v0.4.24.
- [ ] Prevent overflow and underflow
- [ ] Function Visibility
- [ ] Ensure that all relevant functions are marked with the correct visibility
- [ ] Fix compiler warnings
- [ ] Avoid using problematic features - If you must, be aware of their many nuances
- [ ] send (nuances)
- [ ] Low level functions (
call
, delegatecall
, callcode
, inline assembly)
- [ ] var
- [ ] External Calls - Every external contract call is a risk
- [ ] Check for reentrancy - and ensure state committed before external call
- [ ] Check for "short circuits" (external contract calls that can fail or be manipulated to fail, causing a denial of service of a function)
- [ ] Dependencies
- [ ] Use audited and trustworthy dependencies
- [ ] Ensure newly written code is minimized by using libraries
- [ ] Time Manipulation - Timestamps can theoretically be manipulated by malicious miners by up to a few minutes
- [ ] Ensure important mechanisms aren't overly sensitive to timestamps
- [ ] Rounding Errors
- [ ] Check that truncation doesn't produce unexpected behavior (eg. incorrect results, locked funds)
- [ ] Randomness
- [ ] Don't rely on pseudo-randomness for important mechanisms (eg. keccak with a deterministic seed like blockhash, blocknumber, etc.)
- [ ] Validate inputs of external/public functions
- [ ] Ensure requires to bound and check presence of arguments
- [ ] Prevent unbounded loops
- [ ] Appropriate use of push payments
- [ ] Change old Solidity constructs
- [ ] selfdestruct vs suicide
- [ ] keccak256 vs sha3
- [ ] Don't use tx.origin as an authentication mechanism
- [ ] Verify changes in the most recent Solidity version (if upgrading from an older version)
Testing and Software Engineering
- [ ] Test Coverage
- [ ] Have 100% branch test coverage
- [ ] Unit Tests
- [ ] Cover all critical edge cases with unit tests
- [ ] Integration Tests
- [ ] Have extensive integration tests
- [ ] Code Freeze
- [ ] Don't deploy recently written code, especially when written under a tight deadline
Resilience
We always check for code that will mitigate risk when (not if) a contract fails. When a contract doesn’t have this, it’s often a warning sign.
- [ ] What failure states would be most disastrous?
- [ ] Are there assert checks for critical values? (e.g., individual balances total to sum)
- [ ] Speed Bumps
- [ ] Does the contract have a speed bump? (e.g., delay in withdrawing funds, like the DAO)
- [ ] Circuit Breakers
- [ ] Does the contract have a circuit breaker? (preventing critical functions in an emergency mode)
Auditing
Auditing helps catch many bugs, but shouldn’t also be seen as a magic bullet. Your system still needs to handle failure gracefully.
- [ ] Audits
- [ ] Have code audited by (preferably) multiple external parties (in series)
- [ ] Time Management
- [ ] Allocate comfortable time after the audit to address issues
High Risk Areas
When performing an audit, CryptoFin pays special attention to the these areas which require greater scrutiny, as they often add bugs.
- external and public functions
- Assembly code and other low level calls
- Superuser privileges
- Any areas that are affected by timing and/or network congestion
- Areas dealing with value transfer and payable functions
- Push payments (rather than pull)
- Code written most recently
最後歡迎大家拍打餵食大學生0x2b83c71A59b926137D3E1f37EF20394d0495d72d